package com.feishu.core;

import cn.hutool.extra.spring.SpringUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.AES;
import com.feishu.base.dto.HttpClientTokenDTO;
import com.feishu.base.dto.entity.ExecutionTypeDO;
import com.feishu.base.type.AttributesInterfaceType;
import com.feishu.base.type.ClassificationTypeEnum;
import com.feishu.base.type.OutJsonTypeEnum;
import com.feishu.entity.AuthorizationEntity;
import com.feishu.entity.HttpClientTokenVO;
import com.feishu.rpc.core.SendHttpServer;
import com.feishu.rpc.http.RemoteSocketWrapper;
import com.feishu.rpc.http.service.RemoteProcedureCallService;
import com.feishu.rpc.http.service.RemoteProcedureNodeCallService;
import com.feishu.service.FeiShuCommonService;
import com.hustcad.plm.pdm.flowbusiness.model.entity.FlowObject;
import com.hustcad.plm.pdm.partbom.vo.PartDetailsVO;
import com.ty.basic.exception.message.SystemErrorCodeEnum;
import org.apache.http.client.methods.HttpRequestBase;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * 飞书接口
 */
@Service
@AttributesInterfaceType(typeValue = "feishuProject",classificationValue = "ordinaryMessage")
public class FeiShuRemoteNodeCallServiceImpl implements RemoteProcedureNodeCallService {

    @Override
    public <T> T  getAuthorizationEntity() {
        FeiShuCommonService feiShuCommonService=SpringUtil.getBean(FeiShuCommonService.class);
        Map<String,Object> map=new HashMap<>();
        map.put("title","飞书应用配置");
        List<Map<String,Object>> list=feiShuCommonService.selectFiguration(map);
        if (list.size() > 0) {
            String password = AES.decrypt((String) list.get(0).get("password"), "huazPlm@15999899");
            AuthorizationEntity authorizationEntity = new AuthorizationEntity();
            authorizationEntity.groupId=((String) list.get(0).get("acctid"));
            authorizationEntity.appId=((String) list.get(0).get("username"));
            authorizationEntity.appSecret=(password);
            return (T) authorizationEntity;
        }
        return null;
    }

    @Override
    public HttpClientTokenDTO getToken(Object authorizationEntity, Object obj) {
        if (authorizationEntity instanceof AuthorizationEntity) {
            AuthorizationEntity authorization = (AuthorizationEntity) authorizationEntity;
            ExecutionTypeDO executionTypeDO = (ExecutionTypeDO) obj;
            String protocol = executionTypeDO.getProtocol();
            RemoteSocketWrapper remoteSocketWrapper = SpringUtil.getBean(RemoteSocketWrapper.class);
            try {
                JSONObject login=new JSONObject();
                login.put("app_id",authorization.appId);
                login.put("app_secret",authorization.appSecret);
                HttpClientTokenVO httpClientTokenVO = null;
                if("https".equals(protocol)){
                    JSONObject httpResult = remoteSocketWrapper.httpLoingToJSONObject("https://open.feishu.cn/open-apis/auth/v3/app_access_token/internal", login,null);
                    if(httpResult.getLongValue("code")==0){
                        String token="Bearer "+httpResult.getString("tenant_access_token");
                        Map<String,Object> threadContentMap=new HashMap<>();
                        threadContentMap.put("authorization",authorization);
                        httpClientTokenVO=new HttpClientTokenVO<Map<String,Object>>(threadContentMap);
                        httpClientTokenVO.setHeadTokenValue("Authorization",token);
                    }
                }
                return httpClientTokenVO;
            } catch (Exception e) {
                e.printStackTrace();
                throw SystemErrorCodeEnum.WORK_FLOW_CONTENT_ERROR.getException(e.getMessage());

            }

        }
        return null;
    }

    @Override
    public void setParameter(HttpClientTokenDTO httpClientTokenDTO, PartDetailsVO partDetails, ExecutionTypeDO executionTypeDO, FlowObject flowObject, Object parameter) {
        Map<String,Object> threadContentMap= (Map<String, Object>) httpClientTokenDTO.getThreadContent();
        threadContentMap.put("partDetails",partDetails);
    }

    @Override
    public void changeHttpClientHeaders(HttpClientTokenDTO httpClientTokenDTO, HttpRequestBase httpRequestBase,
                                        ExecutionTypeDO executionTypeDO) {
        Map<String,Object> authorization=httpClientTokenDTO.getAuthorization();
        if(authorization!=null){
            for(Map.Entry<String,Object> entity: authorization.entrySet()){
                httpRequestBase.setHeader(entity.getKey(), (String) entity.getValue());
            }
        }

    }

    @Override
    public boolean needReGetToken(Object obj, ExecutionTypeDO executionTypeDO) {
        if(obj instanceof JSONObject){
            JSONObject json= (JSONObject) obj;
            if(json.getLongValue("code")==99991663){
                return true;
            }
        }
        return false;
    }

    @Override
    public Map<String, Object> sendBefore(HttpClientTokenDTO httpClientTokenDTO, Map<String, Object> outMap,
                                          ExecutionTypeDO executionTypeDO, FlowObject flowObject,Object parameter) {

        if("飞书同步三方审批".equals(executionTypeDO.getLabel())){
            Map<String,Object> threadMap= (Map<String, Object>) parameter;
            JSONObject executionstrategy= (JSONObject) threadMap.get("executionstrategy");
            String processInstanceId= (String) threadMap.get("processInstanceId");
            String plmUserId= (String) threadMap.get("plmUserId");
            String auditStatus= (String) threadMap.get("auditStatus");

            if("一票决策".equals(executionstrategy.getString("name"))){
                List<Map<String,Object>> feishuCodeList= (List<Map<String, Object>>) threadMap.get("feishuCodeList");
                String approvalIdsStr= (String) feishuCodeList.get(0).get("approval_id");
                JSONArray approvalIds=JSONArray.parseArray(approvalIdsStr);
                if(approvalIds.size()>1){
                    List<Map<String,Object>> task_list= (List<Map<String, Object>>) outMap.get("task_list");
                    List<Map<String,Object>> newTaskList=new ArrayList<>();
                    if(task_list!=null){
                        Map<String,Object> task=task_list.get(0);
                        String status= (String) task.get("status");
                        if("DELETED".equals(status)||"TERMINATED".equals(status)){
                            task.put("status","DONE");
                        }

                        for(int i=0;i<approvalIds.size();i++){
                            Map<String,Object> addTask=clone(task);
                            Map<String,Object> links= (Map<String, Object>) addTask.get("links");
                            String mobile_link= (String) links.get("mobile_link");
                            links.put("mobile_link",String.format("%s&plmUserId=%s&processInstanceId=%s",mobile_link,approvalIds.getJSONObject(i).getString("plmUserId"),processInstanceId));
                            links.put("pc_link",String.format("%s&plmUserId=%s&processInstanceId=%s",mobile_link,approvalIds.getJSONObject(i).getString("plmUserId"),processInstanceId));
                            String audit=approvalIds.getJSONObject(i).getString("audit");
                            if(audit!=null){
                                addTask.put("status",audit);
                            }
                            else{
                                String plmId=approvalIds.getJSONObject(i).getString("plmUserId");
                                if(plmUserId.equals(plmId)==false){
                                    addTask.put("status","PENDING");
                                }
                                else {
                                    addTask.put("status",auditStatus);
                                    approvalIds.getJSONObject(i).put("audit",auditStatus);
                                }
                            }
                            addTask.put("user_id",approvalIds.getJSONObject(i).getString("feishuId"));
                            addTask.put("task_id",String.format("task_%s_%s",processInstanceId,approvalIds.getJSONObject(i).getString("feishuId")));
                            addTask.put("audit",approvalIds.getJSONObject(i).getString("feishuId"));
                            newTaskList.add(addTask);
                        }
                        outMap.put("task_list",newTaskList);
                    }
                }
                else{
                    List<Map<String,Object>> task_list= (List<Map<String, Object>>) outMap.get("task_list");
                    if(task_list!=null){
                        for(int i=0;i<task_list.size();i++){
                            Map<String,Object> task=task_list.get(i);
                            String status= (String) task.get("status");
                            if("DELETED".equals(status)||"TERMINATED".equals(status)){
                                task.put("status","DONE");
                            }
                        }
                    }
                }
                feishuCodeList.get(0).put("approval_id",approvalIds.toJSONString());
                outMap.put("status","PENDING");
            }
        }

        System.out.println(JSONObject.toJSONString(outMap));
        return outMap;
    }

    @Override
    public JSONObject sendAfter(JSONObject result, ExecutionTypeDO executionTypeDO, FlowObject flowObject,Object parameter) {
        if(result.containsKey("code")){
            if(result.getLongValue("code")==0){
                Map<String,Object> threadMap= (Map<String, Object>) parameter;
                JSONObject executionstrategy= (JSONObject) threadMap.get("executionstrategy");
                if("一票决策".equals(executionstrategy.getString("name"))){
                    FeiShuCommonService feiShuCommonService = SpringUtil.getBean(FeiShuCommonService.class);
                    List<Map<String,Object>> feishuCodeList= (List<Map<String, Object>>) threadMap.get("feishuCodeList");
                    feiShuCommonService.updateFeiShuApprovalCodeApproval(feishuCodeList.get(0));
                }
            }
        }
        return null;
    }

    @Override
    public JSONObject reconstructResult(JSONObject result, ExecutionTypeDO executionTypeDO) {

        return null;
    }

    public Map<String, Object> clone(Map<String, Object> srcMap) {
        Map<String, Object> descMap = new HashMap<>();
        cloneMap(descMap, srcMap);
        return descMap;
    }

    public void cloneMap(Map<String, Object> descMap, Map<String, Object> srcMap) {
        Set<Map.Entry<String, Object>> set = srcMap.entrySet();
        for (Map.Entry<String, Object> entity : set) {
            Object obj = entity.getValue();
            if (obj instanceof Map) {
                descMap.put(entity.getKey(), new HashMap<>());
                cloneMap((Map<String, Object>) descMap.get(entity.getKey()), (Map<String, Object>) obj);
            } else if (obj instanceof List) {
                List list = (List) obj;
                if (list != null) {
                    if (list.size() > 0) {
                        if (list.get(0) instanceof Map) {
                            List<Map<String, Object>> addList = new ArrayList<>();
                            Map<String, Object> addMap = new HashMap<>();
                            addList.add(addMap);
                            descMap.put(entity.getKey(), addList);
                            cloneMap(descMap, addMap);
                        } else {
                            descMap.put(entity.getKey(), entity.getValue());
                        }
                    }
                }
            } else {
                descMap.put(entity.getKey(), entity.getValue());
            }
        }
    }

}
